package com.hex.ds.code.detection.pack.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import com.hex.ds.code.detection.common.entity.ScriptPackScanItemEntity;
import com.hex.ds.code.detection.config.dao.ConfigPathGitMapper;
import com.hex.ds.code.detection.config.model.ConfigPathGit;
import com.hex.ds.code.detection.metadata.service.ScanMetadataService;
import com.hex.ds.code.detection.pack.entity.CheckInitImportEntity;
import com.hex.ds.code.detection.pack.entity.CheckPeriodImportEntity;
import com.hex.ds.code.detection.pack.entity.CheckServiceImportEntity;
import com.hex.ds.code.detection.pack.entity.ScriptPackScanListEntity;
import com.hex.ds.code.detection.pack.entity.ScriptPackTaskEntity;
import com.hex.ds.code.detection.pack.enums.FileScanEnum;
import com.hex.ds.code.detection.pack.service.IScanScriptFileService;
import com.hex.ds.code.detection.pack.service.IScriptPackScanItemService;
import com.hex.ds.code.detection.pack.service.IScriptPackScanListService;
import com.hex.ds.code.detection.pack.service.IScriptPackTaskService;
import com.hex.ds.code.detection.pack.service.IScriptScanService;
import com.hex.ds.code.detection.common.service.ClusterSparingConfService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy, @Autowired})
public class ScriptScanServiceImpl implements IScriptScanService {

    private final ClusterSparingConfService clusterSparingConfService;

    private final IScriptPackTaskService scriptPackTaskService;

    private final IScriptPackScanListService scriptPackScanListService;

    private final IScriptPackScanItemService scriptPackScanItemService;

    private final IScanScriptFileService scanScriptFileService;

    private final ScanMetadataService scanMetadataService;

    private final ConfigPathGitMapper configPathGitMapper;

    private final static String PACK_PATH_TMPLATE = "{}/pack/{}/{}/";

    @Value("${script.pack.relativePath}")
    private String relativePath;

    @Value("${script.scan.masterPackagePath}")
    private String masterPackagePath;

    @Value("${script.scan.initFilePath}")
    private String initFilePath;

    @Value("${script.scan.serviceFilePath}")
    private String serviceFilePath;

    @Value("${script.scan.periodFilePath}")
    private String periodFilePath;

    /**
     * @Method putFilePath
     * @Param id
     * @Return void
     * @Description 如果为git则赋值文件路径
     * @Author le.zhang
     * @Date 2024/3/5 13:29
     * @Version V1.0
     */
    public ConfigPathGit putFilePath(String id){
        ScriptPackTaskEntity scriptPackTaskEntity = scriptPackTaskService.getById(id);
        ConfigPathGit configPathGit = configPathGitMapper.findByGitpath(scriptPackTaskEntity.getGitUrl());
        return configPathGit;
    }

    /**
     * @Method scriptFileScan
     * @Param
     * @param scriptPackTask
     * @Return boolean
     * @Description 脚本文件扫描
     * @Author Wang zhihao
     * @Date 2023/10/11 10:33
     * @Version V1.0
     */
    @Override
    public boolean scriptFileScan(ScriptPackTaskEntity scriptPackTask) {
        try {
            // 获取总包名
            String masterPackageArchivePath = StrUtil.format(PACK_PATH_TMPLATE, relativePath, scriptPackTask.getId(), masterPackagePath);
            List<String> allDirName = getAllDir(masterPackageArchivePath);
            if (CollectionUtil.isNotEmpty(allDirName)) {
                String rootFilePath = allDirName.get(0).replace("\\","/");
                // ① 扫描检查清单
                scanCheckList(rootFilePath, scriptPackTask.getId());
                // ② 创建扫描List清单
                List<ScriptPackScanListEntity> scriptPackScanListEntityList = createServiceScanList(rootFilePath, scriptPackTask.getId(), scriptPackTask.getFileObtainingType());
//                Map<String, List<ScriptPackScanListEntity>> scriptPackScanMaps = createScanList(rootFilePath, scriptPackTask.getId(),scriptPackTask.getFileObtainingType());
//                checkAllListsEmpty(scriptPackScanMaps);
                // 获取集群名
                String clusterName = clusterSparingConfService.getById(scriptPackTask.getClusterId()).getClusterName();
                // ③ 扫描初始化脚本
//                scanInitScript(scriptPackScanListEntityList, rootFilePath, clusterName);
                // ④ 扫描业务脚本
//                scanServiceScript(scriptPackScanListEntityList, rootFilePath, clusterName);
                // ⑤ 扫描周期脚本
                scanPeriodScript(scriptPackScanListEntityList, rootFilePath, clusterName);
            } else {
                throw new RuntimeException("【脚本文件扫描】异常: 获取压缩包内容为空");
            }
            return true;
        } catch (Exception e) {
            log.error("脚本扫描发生异常{}", e.getMessage(), e);
            throw new RuntimeException("脚本扫描发生异常:" + e.getMessage(), e);
        }
    }

    /**
     * @Method checkAllListsEmpty
     * @Param
     * @param map
     * @Return boolean
     * @Description 校验扫描清单是否为空
     * @Author Wang zhihao
     * @Date 2024/1/24 18:52
     * @Version V1.0
     */
    private void checkAllListsEmpty(Map<String, List<ScriptPackScanListEntity>> map) {
        boolean allListsEmpty = map.values().stream().allMatch(List::isEmpty);
        if (allListsEmpty) {
            throw new RuntimeException("检测到该包内不存在符合扫描的文件，请检查");
        }
    }

    /**
     * @Method createScanList
     * @Param
     * @param filePath
     * @param taskId
     * @Return java.util.Map<java.lang.String,java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>>
     * @Description 创建扫描清单
     * @Author Wang zhihao
     * @Date 2023/10/24 13:20
     * @Version V1.0
     */
    private Map<String, List<ScriptPackScanListEntity>> createScanList(String filePath, String taskId,String fileObtainingType) {
        Map<String, List<ScriptPackScanListEntity>> scriptPackScanListMaps = new HashMap<>();

//        scriptPackScanListMaps.put("init", createInitScanList(filePath, taskId, fileObtainingType));
//        scriptPackScanListMaps.put("service", createServiceScanList(filePath, taskId, fileObtainingType));
//        scriptPackScanListMaps.put("period", createPeriodScanList(filePath, taskId, fileObtainingType));
        return scriptPackScanListMaps;
    }

    /**
     * @Method createInitScanList
     * @Param
     * @param filePath
     * @param taskId
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description 创建初始化脚本扫描清单
     * @Author Wang zhihao
     * @Date 2023/10/24 13:20
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> createInitScanList(String filePath, String taskId, String fileObtainingType) {
        String path = "";
        if (StrUtil.equals("git",fileObtainingType)) {
           path = putFilePath(taskId).getInitfilepath();
        }else {
            path = initFilePath;
        }
//        List<String> linuxPath = getAbsolutePath(filePath + initFilePath).stream().map(s -> s.replace("\\", "/")).collect(Collectors.toList());
        List<String> linuxPath = getAbsolutePath(filePath + path).stream().map(s -> s.replace("\\", "/")).collect(Collectors.toList());
        return addScanList(linuxPath, taskId);
    }

    /**
     * @Method createServiceScanList
     * @Param
     * @param filePath
     * @param taskId
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description 创建业务脚本扫描清单
     * @Author Wang zhihao
     * @Date 2023/10/24 13:20
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> createServiceScanList(String filePath, String taskId, String fileObtainingType) {
        String path = "";
        if (StrUtil.equals("git",fileObtainingType)) {
            path = putFilePath(taskId).getServicefilepath();
        }else {
            path = serviceFilePath;
        }
//        List<String> allAbsolutePath = getAbsolutePath(filePath + serviceFilePath);
        List<String> allAbsolutePath = getAbsolutePath(filePath);
        return addScanList(allAbsolutePath, taskId);

    }

    /**
     * @Method createPeriodScanList
     * @Param
     * @param filePath
     * @param taskId
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description 创建周期脚本扫描清单
     * @Author Wang zhihao
     * @Date 2023/10/24 13:21
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> createPeriodScanList(String filePath, String taskId, String fileObtainingType) {
        String path = "";
        if (StrUtil.equals("git",fileObtainingType)) {
            path = putFilePath(taskId).getPeriodfilepath();
        }else {
            path = periodFilePath;
        }
        List<String> allAbsolutePath = getAbsolutePath(filePath +path).stream()
                .filter(s -> StrUtil.endWithAny(s, ".sql", ".hql", ".sh")).collect(Collectors.toList());
        return addScanList(allAbsolutePath,  taskId);
    }

    /**
     * @Method addScanList
     * @Param
     * @param allAbsolutePath
     * @param taskId
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description 初始化扫描清单到数据库中
     * @Author Wang zhihao
     * @Date 2023/10/24 13:21
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> addScanList(List<String> allAbsolutePath, String taskId) {
        List<ScriptPackScanListEntity> scriptPackScanListEntities = new ArrayList<>();
        for (String absolutePath : allAbsolutePath) {
            String fileName = FileNameUtil.getName(absolutePath);
            ScriptPackScanListEntity scriptPackScanList = new ScriptPackScanListEntity()
                    .setScriptPackTaskId(taskId)
                    .setScanFilePath(absolutePath)
                    .setScanFileName(fileName)
                    .setScanState("UNSCAN");
            scriptPackScanListService.save(scriptPackScanList);
            scriptPackScanListEntities.add(scriptPackScanList);
        }
        return scriptPackScanListEntities;
    }

    /**
     * @Method scanCheckList
     * @Param dirName
     * @Return boolean
     * @Description 扫描上线检查清单
     * @Author Wang zhihao
     * @Date 2023/9/15 11:32
     * @Version V1.0
     */
    public boolean scanCheckList(String dirName, String taskId) {
        try {
            // 获取所有checkList清单
            int total = getAllFileName(dirName);
          /*  // 检查初始化脚本文件
            int initTotal = checkInitFile(allCheckList, dirName);
            // 检查业务脚本文件
            int serviceTotal = checkServiceFile(allCheckList, dirName);*/
            // 检查周期脚本文件
            // int periodTotal = checkPeriodFile(allCheckList, dirName);
            scriptPackTaskService.updateById(new ScriptPackTaskEntity()
                    .setId(taskId)
                    .setMasterPackagePath(dirName)
                    .setScanTotal(total)
                    .setScanSuccessNumber(0).setScanWarnNumber(0).setScanErrorNumber(0).setScanFailNumber(0)
            );
        } catch (Exception e) {
            scriptPackTaskService.removeById(taskId);
            log.error("【扫描上线检查清单】异常: {}", e.getMessage(), e);
            throw new RuntimeException( "【扫描上线检查清单】异常: " + e.getMessage(), e);
        }
        return false;
    }

    /**
     * @Method readInitScript
     * @Param
     * @param allCheckList
     * @param archivePackageDir
     * @Return java.util.List<java.lang.String>
     * @Description 多个Excel文件中读取所有的初始脚本文件
     * @Author Wang zhihao
     * @Date 2023/12/12 20:24
     * @Version V1.0
     */
    private List<String> readInitScript(List<String> allCheckList, String archivePackageDir) {
        List<String> initScript = new ArrayList<>();
        for (String fileName : allCheckList) {
            ImportParams importParams = new ImportParams();
            importParams.setStartSheetIndex(1);
            ExcelImportResult<CheckInitImportEntity> checkListInfo = ExcelImportUtil.importExcelMore(new File(archivePackageDir + "/" + fileName), CheckInitImportEntity.class, importParams);
            // 读取Excel中所有的文件名
            List<CheckInitImportEntity> checkInitImportEntities = checkListInfo.getList().stream().filter(s -> !StrUtil.isBlank(s.getFileName())).collect(Collectors.toList());
            Set<String> initName = checkInitImportEntities.stream().map(s->(s.getScriptType() + "/" + s.getFileName())).collect(Collectors.toSet());
            initScript.addAll(new ArrayList<>(initName));
        }
        return initScript;
    }

    /**
     * @Method readServiceScript
     * @Param
     * @param allCheckList
     * @param archivePackageDir
     * @Return java.util.List<java.lang.String>
     * @Description 多个Excel文件中读取所有的推送下载稽核脚本文件
     * @Author Wang zhihao
     * @Date 2023/12/13 14:43
     * @Version V1.0
     */
    private List<String> readServiceScript(List<String> allCheckList, String archivePackageDir) {
        List<String> serviceScript = new ArrayList<>();
        for (String fileName : allCheckList) {
            ImportParams importParams = new ImportParams();
            importParams.setStartSheetIndex(2);
            ExcelImportResult<CheckServiceImportEntity> checkListInfo = ExcelImportUtil.importExcelMore(new File(archivePackageDir + "/" + fileName), CheckServiceImportEntity.class, importParams);
            List<CheckServiceImportEntity> checkServiceImportEntities = checkListInfo.getList().stream().filter(s -> !StrUtil.isBlank(s.getFileName())).collect(Collectors.toList());
            // 读取Excel中所有文件名
            Set<String> initName = checkServiceImportEntities.stream().map(s->(s.getConfigLibrary() + "/" + s.getFileName())).collect(Collectors.toSet());
            serviceScript.addAll(new ArrayList<>(initName));
        }
        return serviceScript;
    }

    /**
     * @Method readPeriodScript
     * @Param
     * @param allCheckList
     * @param archivePackageDir
     * @Return java.util.List<java.lang.String>
     * @Description 多个Excel文件中读取所有的周期脚本文件
     * @Author Wang zhihao
     * @Date 2023/12/13 14:43
     * @Version V1.0
     */
    private List<String> readPeriodScript(List<String> allCheckList, String archivePackageDir) {
        List<String> periodScript = new ArrayList<>();
        for (String fileName : allCheckList) {
            ImportParams importParams = new ImportParams();
            importParams.setStartSheetIndex(0);
            ExcelImportResult<CheckPeriodImportEntity> checkListInfo = ExcelImportUtil.importExcelMore(new File(archivePackageDir + "/" + fileName), CheckPeriodImportEntity.class, importParams);
            List<CheckPeriodImportEntity> checkPeriodImportEntities = checkListInfo.getList().stream().filter(s -> !StrUtil.isBlank(s.getFileName())).collect(Collectors.toList());
            // 读取Excel中所有文件名
            Set<String> periodName = checkPeriodImportEntities.stream().filter(s -> !StrUtil.equalsIgnoreCase(s.getChangeType(), "下线")).map(CheckPeriodImportEntity::getFileName).collect(Collectors.toSet());
            periodScript.addAll(new ArrayList<>(periodName));
        }
        return periodScript;
    }

    /**
     * @Method checkInitFile
     * @Param
     * @Return void
     * @Description 根据上线清单检查初始化脚本文件
     * @Author Wang zhihao
     * @Date 2023/10/10 14:04
     * @Version V1.0
     */
    private Integer checkInitFile(List<String> allCheckList, String archivePackageDir) {
        try {
            // 获取所有的上线清单中的脚本名及脚本类别
            List<String> recordScriptName = readInitScript(allCheckList, archivePackageDir);
            // 获取上传包中的初始化脚本文件及其上级目录
            List<String> initFileName = getAbsolutePath(archivePackageDir + "/交付物/初始化脚本");
            List<String> updateScriptName = initFileName.stream().map(s -> s.replace("\\", "/"))
                    .map(s -> Arrays.stream(s.split("/")).skip(s.split("/").length - 2).collect(Collectors.joining("/"))).collect(Collectors.toList());
            checkInitFileName(initFileName);
            if (!CollectionUtils.isEqualCollection(recordScriptName, updateScriptName)) {
                throwErr(recordScriptName, updateScriptName, FileScanEnum.INIT.getDesc());
            }
            return updateScriptName.size();
        } catch (Exception e) {
            log.error("根据上线清单检查初始化脚本文件异常: {}", e.getMessage(), e);
            throw new RuntimeException("根据上线清单检查初始化脚本文件异常: " + e.getMessage(), e);
        }
    }

    /**
     * @Method checkServiceFile
     * @Param
     * @param allCheckList
     * @param archivePackageDir
     * @Return void
     * @Description 根据上线清单检查推送下载稽核脚本
     * @Author Wang zhihao
     * @Date 2023/12/13 10:50
     * @Version V1.0
     */
    private Integer checkServiceFile(List<String> allCheckList, String archivePackageDir) {
        try {
            // 获取所有的上线清单中的脚本名及配置库
            List<String> recordScriptName = readServiceScript(allCheckList, archivePackageDir);
            // 获取上传包中的初始化脚本文件及其上级目录
            List<String> serviceFileName = getAbsolutePath(archivePackageDir + "/交付物/下载推送稽核");
            List<String> updateScriptName = serviceFileName.stream().map(s -> s.replace("\\", "/"))
                    .map(s -> Arrays.stream(s.split("/")).skip(s.split("/").length - 2).collect(Collectors.joining("/"))).collect(Collectors.toList());
            if (!CollectionUtils.isEqualCollection(recordScriptName, updateScriptName)) {
                throwErr(recordScriptName, updateScriptName, FileScanEnum.SERVICE.getDesc());
            }
            return updateScriptName.size();
        } catch (Exception e) {
            log.error("根据上线清单检查推送下载稽核脚本文件异常: {}", e.getMessage(), e);
            throw new RuntimeException("根据上线清单检查推送下载稽核脚本文件异常: " + e.getMessage(), e);
        }
    }

    /**
     * @Method checkPeriodFile
     * @Param
     * @param allCheckList
     * @param archivePackageDir
     * @Return void
     * @Description 根据上线清单周期脚本
     * @Author Wang zhihao
     * @Date 2023/12/13 14:23
     * @Version V1.0
     */
    private Integer checkPeriodFile(List<String> allCheckList, String archivePackageDir) {
        try {
            // 获取所有的上线清单中的脚本名及路径
            List<String> recordScriptName = readPeriodScript(allCheckList, archivePackageDir);
            // 获取所有上传包中的周期脚本
            List<String> periodFileName = getAbsolutePath(archivePackageDir + "/");
            List<String> updateScriptName = periodFileName.stream().map(s -> s.replace("\\", "/"))
                    .map(s -> s.split("/")[s.split("/").length-1]).collect(Collectors.toList());
            if (!CollectionUtils.isEqualCollection(recordScriptName, updateScriptName)) {
                throwErr(recordScriptName, updateScriptName, FileScanEnum.PERIOD.getDesc());
            }
            // 获取实际会扫描的文件数量做返回
            List<String> scanScriptName = updateScriptName.stream()
                    .filter(s -> StrUtil.endWithAny(s, ".sql", ".hql", ".sh")).collect(Collectors.toList());
            return scanScriptName.size();
        } catch (Exception e) {
            log.error("根据上线清单检查周期脚本文件异常: {}", e.getMessage(), e);
            throw new RuntimeException("根据上线清单检查周期脚本文件异常: " + e.getMessage(), e);
        }
    }

    /**
     * @Method throwErr
     * @Param
     * @param checkFileSet
     * @param realFileSet
     * @param checkType
     * @Return void
     * @Description 抛出checkList文件检查后的详细异常情况
     * @Author Wang zhihao
     * @Date 2023/10/10 19:01
     * @Version V1.0
     */
    private void throwErr(List<String> checkFileSet, List<String> realFileSet, String checkType) {
        if (checkFileSet.size() >= realFileSet.size()) {
            String diff = checkFileSet.stream().filter(s -> !CollectionUtil.contains(realFileSet, s))
                    .collect(Collectors.joining("\n"));
            throw new RuntimeException(checkType + "清单检查异常, 上传脚本缺少如下脚本：\n" + diff);
        } else {
            String diff = realFileSet.stream().filter(s -> !CollectionUtil.contains(checkFileSet, s))
                    .collect(Collectors.joining("\n"));
            throw new RuntimeException(checkType + "清单检查异常, 上传脚本比清单多出如下脚本：\n" + diff);
        }
    }

    /**
     * @Method scanInitScript
     * @Param
     * @param scriptPackScanListEntities
     * @param filePath
     * @Return boolean
     * @Description 扫描初始化脚本文件
     * @Author Wang zhihao
     * @Date 2023/10/24 13:30
     * @Version V1.0
     */
    public boolean scanInitScript(List<ScriptPackScanListEntity> scriptPackScanListEntities, String filePath, String clusterName) {
        try {
            if (CollectionUtil.isNotEmpty(scriptPackScanListEntities)) {
                // 检查脚本文件内容
                checkInitFileContent(scriptPackScanListEntities, clusterName);
            } else {
                log.warn("检查到该目录" + filePath + initFilePath + "可能不存在或目录下没有符合的文件，请检查");
            }
            return true;
        } catch (Exception e) {
            log.error("初始化脚本扫描发生异常{}", e.getMessage(), e);
            throw new RuntimeException("初始化脚本扫描发生异常" + e.getMessage(), e);
        }
    }

    /**
     * @Method scanServiceScript
     * @Param filePath
     * @Return boolean
     * @Description 扫描业务脚本文件
     * @Author Wang zhihao
     * @Date 2023/9/15 11:32
     * @Version V1.0
     */
    public boolean scanServiceScript(List<ScriptPackScanListEntity> scriptPackScanListEntities, String filePath, String clusterName) {
        try {
            if (CollectionUtil.isNotEmpty(scriptPackScanListEntities)) {
                // 检查脚本文件内容
                checkServiceFileContent(scriptPackScanListEntities, clusterName);
            } else {
                log.warn("检查到该目录" + filePath + serviceFilePath + "可能不存在或目录下没有符合的文件，请检查");
            }
            return true;
        } catch (Exception e) {
            log.error("业务脚本扫描发生异常{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * @Method scanPeriodScript
     * @Param filePath
     * @Return boolean
     * @Description 扫描周期脚本文件
     * @Author Wang zhihao
     * @Date 2023/9/15 11:33
     * @Version V1.0
     */
    public boolean scanPeriodScript(List<ScriptPackScanListEntity> scriptPackScanListEntities, String filePath, String clusterName) {
        try {
            if (CollectionUtil.isNotEmpty(scriptPackScanListEntities)) {
                // ② 检查脚本文件内容
                checkPeriodFileContent(scriptPackScanListEntities, clusterName);
            } else {
                log.warn("检查到该目录" + filePath + periodFilePath + "可能不存在或目录下没有符合的文件，请检查");
            }
            return true;
        } catch (Exception e) {
            log.error("周期脚本扫描发生异常{}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * @param dir
     * @Method getAllFileName
     * @Param
     * @Return java.util.List<java.lang.String>
     * @Description 获取目录下所有文件名
     * @Author Wang zhihao
     * @Date 2023/9/15 15:25
     * @Version V1.0
     */
    public int getAllFileName(String dir) {
        List<String> allFileName = new ArrayList<>();
        if (FileUtil.isDirectory(dir)) {
            allFileName = FileUtil.listFileNames(dir);
        }
        return allFileName.size();
    }

    /**
     * @Method getAllFileName
     * @Param
     * @param dir
     * @Return java.util.List<java.lang.String>
     * @Description 获取目录下所有目录
     * @Author Wang zhihao
     * @Date 2023/9/15 15:25
     * @Version V1.0
     */
    public List<String> getAllDir(String dir) {
        List<String> allDir = new ArrayList<>();
        File file = new File(dir);
        File[] files = file.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    allDir.add(f.getAbsolutePath());
                }
            }
        }
        return allDir;
    }

    /**
     * @Method getAbsolutePath
     * @Param
     * @param dir
     * @Return java.util.List<java.lang.String>
     * @Description 获取路径下所有文件的绝对路径
     * @Author Wang zhihao
     * @Date 2023/10/12 17:38
     * @Version V1.0
     */
    public List<String> getAbsolutePath(String dir) {
        return FileUtil.loopFiles(dir).stream().map(File::getAbsolutePath).collect(Collectors.toList());
    }

    /**
     * @Method checkInitFileName
     * @Param
     * @Return void
     * @Description 检查脚本名
     * @Author Wang zhihao
     * @Date 2023/9/15 15:37
     * @Version V1.0
     */
    private void checkInitFileName(List<String> fileNames) {
        fileNames = fileNames.stream().filter(s -> s.endsWith(".sql") || s.endsWith(".hql")).collect(Collectors.toList());
        for (String fileName : fileNames) {
            if (!checkNameSuffix(fileName)) {
                log.error("初始化脚本文件名检查失败：存在结尾不符合初始化脚本的文件: {}", fileName);
                throw new RuntimeException("存在结尾不符合初始化脚本的文件: \n" + fileName);
            }
            if (!checkNameRegular(fileName, FileScanEnum.FILE_NAME_REGULAR.getValue())) {
                log.error("初始化脚本文件名检查失败：存在文件名不符合正则规则的文件名: {}", fileName);
                throw new RuntimeException("存在文件名不符合正则规则的文件名: \n" + fileName);
            }
        }
    }

    public boolean checkNameSuffix(String fileName) {
        return StrUtil.endWithAny(fileName,
                FileScanEnum.INIT_FILE_SUFFIX1.getValue(),
                FileScanEnum.INIT_FILE_SUFFIX2.getValue(),
                FileScanEnum.INIT_FILE_SUFFIX3.getValue(),
                FileScanEnum.INIT_FILE_SUFFIX4.getValue(),
                FileScanEnum.INIT_FILE_SUFFIX5.getValue(),
                FileScanEnum.HQL_SUFFIX.getValue());
    }

    public boolean checkNameRegular(String filePath, String regular) {
        String fileName = FileNameUtil.getName(filePath);
        return StrUtil.subBefore(fileName, ".", true).matches(regular);
    }

    /**
     * @Method checkInitFileContent
     * @Param
     * @Return void
     * @Description 检查脚本文件内容
     * @Author Wang zhihao
     * @Date 2023/9/15 15:37
     * @Version V1.0
     */
    private void checkInitFileContent(List<ScriptPackScanListEntity> scriptPackScanListEntities, String clusterName) {
        // 获取初始化脚本扫描项
        List<ScriptPackScanItemEntity> scriptPackScanItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.INIT.getValue());
        // 获取hive_sql脚本扫描项--20240417新增需求
        List<ScriptPackScanItemEntity> scriptPackScanHqlItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.HIVE_SQL.getValue());
        List<String> timePartitionTableList = scanMetadataService.queryTimePartitionTable();
        // Oracle脚本处理
        dealOracleScript(scriptPackScanListEntities);
        // shell脚本处理
        List<ScriptPackScanItemEntity> scriptPackScanShellItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.INIT_SHELL.getValue());
        dealShellScript(scriptPackScanListEntities, scriptPackScanShellItemList);
        // 异步扫描初始化脚本
        scriptPackScanListEntities.forEach(scriptPackScanList -> {
            scanScriptFileService.scanInitScriptFile(scriptPackScanItemList, scriptPackScanHqlItemList, scriptPackScanList, timePartitionTableList, clusterName);
        });
    }

    /**
     * @Method dealOracleScript
     * @Param
     * @param scriptPackScanListEntities
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description Oracle脚本处理
     * @Author Wang zhihao
     * @Date 2024/1/29 19:18
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> dealOracleScript(List<ScriptPackScanListEntity> scriptPackScanListEntities) {
        List<ScriptPackScanListEntity> oracleFile = scriptPackScanListEntities.stream().filter(s -> "oracle".equalsIgnoreCase(s.getScanFilePath().split("/")[s.getScanFilePath().split("/").length-2])).collect(Collectors.toList());
        for (ScriptPackScanListEntity fileInfo : oracleFile) {
            scriptPackScanListService.updateStatus(fileInfo.getId(), "SUCCESS");
            scriptPackTaskService.modifyScanSuccessNum(fileInfo.getScriptPackTaskId());
        }
        scriptPackScanListEntities.removeAll(oracleFile);
        return scriptPackScanListEntities;
    }

    /**
     * @Method dealShellScript
     * @Param
     * @param scriptPackScanListEntities
     * @Return java.util.List<com.hex.ds.code.detection.script.pack.entity.ScriptPackScanListEntity>
     * @Description shell脚本处理
     * @Author Wang zhihao
     * @Date 2024/1/29 19:28
     * @Version V1.0
     */
    private List<ScriptPackScanListEntity> dealShellScript(List<ScriptPackScanListEntity> scriptPackScanListEntities, List<ScriptPackScanItemEntity> scriptPackScanItemList) {
        List<ScriptPackScanListEntity> shellFile = scriptPackScanListEntities.stream().filter(s -> s.getScanFileName().endsWith(".sh")).collect(Collectors.toList());
        shellFile.forEach(scriptPackScanList -> {
            scanScriptFileService.scanShellScriptFile(scriptPackScanItemList, scriptPackScanList);
        });
        scriptPackScanListEntities.removeAll(shellFile);
        return scriptPackScanListEntities;
    }

    /**
     * @Method checkServiceFileContent
     * @Param
     * @param scriptPackScanListEntities
     * @Return void
     * @Description 检查业务脚本文件内容
     * @Author Wang zhihao
     * @Date 2023/10/11 13:29
     * @Version V1.0
     */
    private void checkServiceFileContent(List<ScriptPackScanListEntity> scriptPackScanListEntities, String clusterName) {
        List<ScriptPackScanItemEntity> scriptPackScanItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.SERVICE.getValue());
        scriptPackScanListEntities.forEach(scriptPackScanList -> {
            scanScriptFileService.scanServiceScriptFile(scriptPackScanItemList, scriptPackScanList, clusterName);
        });
    }

    /**
     * @Method checkPeriodFileContent
     * @Param
     * @param scriptPackScanListEntities
     * @Return void
     * @Description 检查周期脚本文件体
     * @Author Wang zhihao
     * @Date 2023/9/15 18:00
     * @Version V1.0
     */
    private void checkPeriodFileContent(List<ScriptPackScanListEntity> scriptPackScanListEntities, String clusterName) {
        // 获取周期脚本扫描项
        List<ScriptPackScanItemEntity> scriptPackScanItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.PERIOD.getValue());
        // 获取hive_sql脚本扫描项--20240417新增需求
        List<ScriptPackScanItemEntity> scriptPackScanHqlItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.HIVE_SQL.getValue());
        List<String> timePartitionTableList = scanMetadataService.queryTimePartitionTable();
        // shell脚本处理
        List<ScriptPackScanItemEntity> scriptPackScanShellItemList = scriptPackScanItemService.getListByScriptType(FileScanEnum.PERIOD_SHELL.getValue());
        dealShellScript(scriptPackScanListEntities, scriptPackScanShellItemList);
        // 异步扫描周期脚本
        scriptPackScanListEntities.forEach(scriptPackScanList -> {
            scanScriptFileService.scanPeriodScriptFile(scriptPackScanItemList, scriptPackScanHqlItemList, scriptPackScanList, timePartitionTableList, clusterName);
        });
    }

}
